package tcln.sors.model.core.util;

import java.util.Set;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.annotation.AnnotationClassFilter;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ClassUtils;

/**
 * Similar to AnnotationMatchingPointcut but this match also beans that have annotations on interface.
 * 
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 */
public class TransactionalBeanPointCut implements Pointcut {
    private final ClassFilter classFilter;

    public TransactionalBeanPointCut() {
        classFilter = new AnnotationClassFilter(Transactional.class) {
            @Override
            @SuppressWarnings("unchecked")
            public boolean matches(final Class clazz) {
                if (super.matches(clazz)) {
                    return true;
                }
                // match interface
                Set<Class> allInterfaces = ClassUtils.getAllInterfacesForClassAsSet(clazz);
                for (Class inf : allInterfaces) {
                    if (inf.isAnnotationPresent(Transactional.class)) {
                        return true;
                    }
                }
                return false;
            }

        };
    }

    @Override
    public ClassFilter getClassFilter() {
        return classFilter;
    }

    @Override
    public MethodMatcher getMethodMatcher() {
        return MethodMatcher.TRUE;
    }

}
